home *** CD-ROM | disk | FTP | other *** search
/ MacHack 1996 / MacHack 1996.toast / Hacks / Hacks ’87 / Source ƒ.sit / Source ƒ / C ƒ / CITADEL BBS 'C' SRC / CONFG.C < prev    next >
C/C++ Source or Header  |  1987-01-14  |  43KB  |  1,287 lines

  1. /************************************************************************/
  2. /*                confg.c                 */
  3. /*    configuration program for Citadel bulletin board system.    */
  4. /************************************************************************/
  5.  
  6. #include "ctdl.h"
  7.  
  8. /************************************************************************/
  9. /*                History                 */
  10. /*                                    */
  11. /* 85Dec26 HAW    Add CALL-LOG define.                    */
  12. /* 85Nov15 HAW    MS-DOS library update.                    */
  13. /* 85Oct27 HAW    Kill CERMETEK.                        */
  14. /* 85Oct17 HAW    Add paramVers, change bauds to array, searchBaud chg.    */
  15. /* 85Oct16 HAW    Kill CLOCK, add officeStuff.                */
  16. /* 85Aug24 HAW    Add duomessage file, NETDISK specification.        */
  17. /* 85Jul07 HAW    Update so won't go through total recon. on init.    */
  18. /* 85May27 HAW    Start stuffing in auto-networking stuff.        */
  19. /* 85May22 HAW    Start conversion to make log file size sysop selectable.*/
  20. /* 85May11 HAW    Make "Lobby" sysop definable                */
  21. /* 85May06 HAW    Add bail out code.                    */
  22. /* 85May05 HAW    Add helpDisk parameter for 3 disk system.        */
  23. /* 85Apr10 HAW    Fix logSort, alphabetize file.                */
  24. /* 85Mar11 HAW    Put all user functions in this file.            */
  25. /* 85Feb18 HAW    Add baud search stuff.                    */
  26. /* 85Jan20 HAW    Use MSDOS #define for date stuff.            */
  27. /* 84Sep05 HAW    Isolate strangeness in compiler's library.  See note.    */
  28. /* 84Aug30 HAW    Onwards to MS-DOS!                    */
  29. /* 84Apr08 HAW    Update to BDS C 1.50a begun.                */
  30. /* 82Nov20 CrT    Created.                        */
  31. /************************************************************************/
  32.  
  33. /************************************************************************/
  34. /*                Contents                */
  35. /*                                    */
  36. /*    dGetWord()        reads a word off disk            */
  37. /*    init()            system startup initialization        */
  38. /*    main()            main controller             */
  39. /*    illegal()        abort bottleneck            */
  40. /*    getMessage()        load message into RAM            */
  41. /*    getMsgChar()        returns successive chars off disk    */
  42. /*    getMsgStr()        reads a string out of message.buf    */
  43. /*    msgInit()        sets up cfg.catChar, catSect etc.    */
  44. /*    startAt()        setup to read a message off disk    */
  45. /*    unGetMsgChar()        return a char to getMsgChar()        */
  46. /*    zapMsgFile()        initialize ctdlmsg.sys            */
  47. /*    realZap()        does work of zapMsgFile()        */
  48. /*    indexRooms()        build RAM index to ctdlroom.sys     */
  49. /*    noteRoom()        enter room into RAM index        */
  50. /*    zapRoomFile()        erase & re-initialize ctdlroom.sys    */
  51. /*    setSpace()        set default disk and user#        */
  52. /*    hash()            hashes a string to an integer        */
  53. /*    logInit()        builds the RAM index to CTDLLOG.SYS    */
  54. /*    noteLog()        enters a userlog record into RAM index    */
  55. /*    sortLog()        sort CTDLLOG by time since last call    */
  56. /*    wrapup()        finishes and writes ctdlTabl.sys    */
  57. /*    zapLogFile()        erases & re-initializes CTDLLOG.SYS    */
  58. /************************************************************************/
  59.  
  60. /************************************************************************/
  61. /*                Strangenesses    (Hue, Jr., 12Sep84)    */
  62. /*    Have discovered that the line:                    */
  63. /*    sscanf(line, "\"%s\"", str);                    */
  64. /*    is not parsed the same way by this compiler as it is by BDS;    */
  65. /*    this is highly unfortunate and excrable.  So, all porters    */
  66. /*    should note that scanf() is not, in any way, "portable."  If    */
  67. /*    BDS is "non-standard", then the standard sucks.         */
  68. /************************************************************************/
  69.  
  70. /************************************************************************/
  71. /*          External variable declarations in CONFG.C        */
  72. /************************************************************************/
  73. extern struct config cfg;    /* The configuration variable        */
  74. static unsigned char GMCCache;    /* To unGetMsgChar() into        */
  75. struct msgB         msgBuf;    /* The -sole- message buffer        */
  76. extern struct netBuffer     netBuf;
  77. FILE             *msgfl;    /* file descriptor for the msg file    */
  78. static int   thisChar;        /* next char in sectBuf         */
  79. static unsigned thisSector;    /* next sector in msgfl         */
  80. static int   oldChar;        /* Old value of thisChar        */
  81. static unsigned oldSector;    /* Old value of thisSector        */
  82. static unsigned char  sectBuf[SECTSIZE];
  83.                    /* ^ msgfl sector buffer (simulated)    */
  84. extern struct rTable roomTab[MAXROOMS]; /* RAM index of rooms        */
  85. extern struct aRoom  roomBuf;        /* room buffer            */
  86. extern FILE     *roomfl;        /* file descriptor for rooms    */
  87. extern int    thisRoom;      /* room currently in roomBuf      */
  88. extern struct logBuffer logBuf;     /* Log buffer of a person    */
  89. extern struct lTable   *logTab;     /* RAM index of pippuls     */
  90. extern int     thisLog;        /* entry currently in logBuf    */
  91. extern FILE      *logfl;        /* log file descriptor        */
  92. extern FILE      *netfl;
  93. char     *baseRoom;
  94. extern struct netTable *netTab;
  95. extern int     thisNet;
  96. long        mailCount=0;
  97. char  msgZap =    FALSE,
  98.       logZap =    FALSE,
  99.       roomZap = FALSE;
  100.  
  101.  
  102. /************************************************************************/
  103. /*        External function definitions for CONFG.C        */
  104. /************************************************************************/
  105. extern FILE   *fopen();
  106. char          toUpper();
  107. unsigned char getMsgChar();
  108. int          fread();
  109. long          fseek();
  110. char          *malloc();
  111.  
  112. /************************************************************************/
  113. /*    init() -- master system initialization                */
  114. /************************************************************************/
  115. init(attended)
  116. int attended;
  117. {
  118.     unsigned char c;
  119.     unsigned      i;
  120.     char      *msgFile, *netFile, *roomFile, *logFile;
  121.  
  122.     cfg.sizeLTentry = sizeof(*logTab);
  123.  
  124.     cfg.debug        = FALSE;
  125.     cfg.noChat        = TRUE;
  126.  
  127.     /* shave-and-a-haircut/two bits pause pattern for ringing sysop: */
  128.     cfg.shave[0]    = 40;
  129.     cfg.shave[1]    = 20;
  130.     cfg.shave[2]    = 20;
  131.     cfg.shave[3]    = 40;
  132.     cfg.shave[4]    = 80;
  133.     cfg.shave[5]    = 40;
  134.     cfg.shave[6]    =250;
  135.  
  136.     /* initialize input character-translation table:    */
  137.     for (c = 0;  c < '\40';  c++) {
  138.     cfg.filter[c] = '\0';        /* control chars -> nulls    */
  139.     }
  140.     for (c='\40'; c < 128;   c++) {
  141.     cfg.filter[c] = c;        /* pass printing chars        */
  142.     }
  143.     cfg.filter[SPECIAL]     = SPECIAL;
  144.     cfg.filter[CNTRLl]        = CNTRLl;
  145.     cfg.filter[DEL    ]   = BACKSPACE;
  146.     cfg.filter[BACKSPACE]   = BACKSPACE;
  147.     cfg.filter[XOFF    ]   = 'P'      ;
  148.     cfg.filter['\r'    ]   = NEWLINE  ;
  149.     cfg.filter[CNTRLO    ]   = 'N'      ;
  150.  
  151.     setSpace(cfg.homeDisk, "");
  152.  
  153.     msgFile    = "a:ctdlmsg.sys";
  154.     *msgFile   += cfg.msgDisk;
  155.     netFile    = "a:ctdlnet.sys";
  156.     *netFile   += cfg.netDisk;
  157.     roomFile    = "a:ctdlroom.sys";
  158.     *roomFile  += cfg.sysDisk;
  159.     logFile    = "a:ctdllog.sys";
  160.     *logFile   += cfg.sysDisk;
  161.  
  162.     /* open message file */
  163.     if ((netfl = fopen(netFile, "rb")) == NULL) {
  164.     printf(" %s not found, creating new file.\n", netFile);
  165.     if ((netfl = fopen(netFile, "wb")) == NULL)
  166.         illegal("?Can't create the net file!");
  167.     }
  168.  
  169.     if ((msgfl = fopen(msgFile, "rwb")) == NULL) {
  170.     if (!attended)
  171.         illegal("!System must be attended for creation!");
  172.     printf(" %s not found, creating new file. \n", msgFile);
  173.     if ((msgfl = fopen(msgFile, "wrb")) == NULL)
  174.         illegal("?Can't create the message file!");
  175.     printf(" (Be sure to initialize it!)\n");
  176.     }
  177.  
  178.     /* open room file */
  179.     if ((roomfl = fopen(roomFile, "rwb")) == NULL) {
  180.     if (!attended)
  181.         illegal("!System must be attended for creation!");
  182.     printf(" %s not found, creating new file. \n", roomFile);
  183.     if ((roomfl = fopen(roomFile, "wrb")) == NULL)
  184.        illegal("?Can't create room file!");
  185.     printf(" (Be sure to initialize it!)\n");
  186.     }
  187.  
  188.     /* open userlog file */
  189.     if ((logfl = fopen(logFile, "rwb")) == NULL) {
  190.     if (!attended)
  191.         illegal("!System must be attended for creation!");
  192.     printf(" %s not found, creating new file. \n", logFile);
  193.     if ((logfl = fopen(logFile, "wrb")) == NULL)
  194.         illegal("?Can't create log file!");
  195.     printf(" (Be sure to initialize it!)\n");
  196.     }
  197.  
  198.     printf("\n Erase and initialize log, message and/or room files?");
  199.     if (attended)
  200.     if (toUpper(getch()) == 'Y') {
  201.         /* each of these has an additional go/no-go interrogation: */
  202.         msgZap  = zapMsgFile();
  203.         roomZap = zapRoomFile();
  204.         logZap  = zapLogFile();
  205.     }
  206. }
  207.  
  208. /************************************************************************/
  209. /*    main() for confg.c                        */
  210. /************************************************************************/
  211. main(argc, argv)
  212. int  argc;
  213. char **argv;
  214. {
  215.     FILE *fBuf, *pwdfl;
  216.     char line[90];
  217.     char cmd[90], var[90], string[90];
  218.     int  arg, arg2, args;
  219.     int  i, j, offset = 0;
  220.     union {
  221.     int          *pi;
  222.     unsigned char *pc;
  223.     } nextCode;     /* where to deposit next code */
  224.  
  225.     cfg.paramVers = 6;
  226.     printf("Citadel-86 Configurator (V%d)\n\n", cfg.paramVers);
  227.     cfg.sysPassword[0] = 0;
  228.     cfg.weAre      = CONFIGUR;
  229.     cfg.MAXLOGTAB = 0;        /* Initialize, just in case        */
  230.     if ((fBuf = fopen("ctdlcnfg.sys", "r")) == NULL) {    /* ASCII mode    */
  231.     printf("?Can't find ctdlCnfg.sys!\n");
  232.     exit();
  233.     }
  234.     nextCode.pc = &cfg.codeBuf[0];
  235.     while (fgets(line, 90, fBuf) != NULL) {
  236.     if (args = sscanf(line, "%s %s %x ", cmd, var, &arg)) {
  237.         if    (strCmp(cmd, "#define" ) == SAMESTRING    &&  args == 3) {
  238.         printf("#define '%s' as %x\n", var, arg);
  239.                if (strCmp(var, "MEGAHZ"    )    == SAMESTRING) {
  240.             cfg.megaHz        = arg;
  241.         } else if (strCmp(var, "CRYPTSEED" )    == SAMESTRING) {
  242.             cfg.cryptSeed   = arg;
  243. #ifndef MSDOS
  244.         } else if (strCmp(var, "CLOCK"       )    == SAMESTRING) {
  245.             cfg.clock        = arg;
  246. #endif
  247.         } else if (strCmp(var, "MESSAGEK"  )    == SAMESTRING) {
  248.                 cfg.maxMSector  = arg*8;
  249.         } else if (strCmp(var, "MSGDISK"   )    == SAMESTRING) {
  250.             cfg.msgDisk     = arg;
  251.         } else if (strCmp(var, "HOMEDISK"  )    == SAMESTRING) {
  252.             cfg.homeDisk    = arg;
  253.         } else if (strCmp(var, "SYSDISK"   )    == SAMESTRING) {
  254.             cfg.sysDisk     = arg;
  255.         } else if (strCmp(var, "NETDISK"   )    == SAMESTRING) {
  256.             cfg.netDisk     = arg;
  257.         } else if (strCmp(var, "LOGINOK"   )    == SAMESTRING) {
  258.             cfg.unlogLoginOk= arg;
  259.         } else if (strCmp(var, "ENTEROK"   )    == SAMESTRING) {
  260.             cfg.unlogEnterOk= arg;
  261.         } else if (strCmp(var, "READOK"    )    == SAMESTRING) {
  262.             cfg.unlogReadOk = arg;
  263.         } else if (strCmp(var, "ROOMOK"    )    == SAMESTRING) {
  264.             cfg.nonAideRoomOk=arg;
  265.         } else if (strCmp(var, "ALLMAIL"   )    == SAMESTRING) {
  266.             cfg.noMail        = !arg;
  267.         } else if (strCmp(var, "SEARCHBAUD")    == SAMESTRING) {
  268.             cfg.search_baud = arg;
  269.         } else if (strCmp(var, "IBM"       )    == SAMESTRING) {
  270.             cfg.IBM_or_clone= arg;
  271.         } else if (strCmp(var, "COM"       )    == SAMESTRING) {
  272.             if (arg == 1) {
  273.             cfg.modem_data = 0x3f8;
  274.             cfg.modem_status = 0x3fd;
  275.             cfg.line_status = 0x3fd;
  276.             }
  277.             else if (arg == 2) {
  278.             cfg.modem_data = 0x2f8;
  279.             cfg.modem_status = 0x2fd;
  280.             cfg.line_status = 0x2fd;
  281.             }
  282.             else illegal("COM port can only currently be 1 or 2");
  283.         } else if (strCmp(var, "TIMEOUT"   )    == SAMESTRING) {
  284.             cfg.dailyTimeout= arg;
  285.         } else if (strCmp(var, "HOUROUT"   )    == SAMESTRING) {
  286.             if ((cfg.hourOut     = arg) > 23 || arg < 0)
  287.             illegal("Illegal value: 0 <= HOUROUT <= 23");
  288.         } else if (strCmp(var, "MIRRORMSG" )    == SAMESTRING) {
  289.             cfg.mirror = arg;
  290.         } else if (strCmp(var, "MSG2DISK"  )    == SAMESTRING) {
  291.             cfg.mbkpDisk = arg;
  292.         } else if (strCmp(var, "LOGSIZE"   )    == SAMESTRING) {
  293.             cfg.MAXLOGTAB   = arg;
  294.             logTab = (struct lTable *) malloc(sizeof(*logTab) * arg);
  295.         } else if (strCmp(var, "NETWORK"   )    == SAMESTRING) {
  296.             cfg.netParticipant = arg;
  297.         } else if (strCmp(var, "LONG-HAUL" )    == SAMESTRING) {
  298.             cfg.longHaul = arg;
  299.         } else if (strCmp(var, "DAYDIV"    )    == SAMESTRING) {
  300.             cfg.dayDiv = arg;
  301.         } else if (strCmp(var, "NETHOUR"   )    == SAMESTRING) {
  302.             cfg.netHour = arg;
  303.         } else if (strCmp(var, "NETLENGTH" )    == SAMESTRING) {
  304.             cfg.netLength = arg;
  305.         } else if (strCmp(var, "SYSBAUD"   )    == SAMESTRING) {
  306.             cfg.sysBaud   = arg;
  307.             if (arg > 3 || arg < 0) {
  308.             illegal(
  309. "Valid SYSBAUD values: 0=300, 1=3/12, 2=3/12/24, 3=3/12/24/Your option");
  310.             }
  311.         } else if (strCmp(var, "CALL-LOG"  )    == SAMESTRING) {
  312.             cfg.call_log  = arg;
  313.         } else {
  314.             printf("? -- no variable '%s' known! -- ignored.\n", var);
  315.         }
  316.  
  317.         } else if (strCmp(cmd, "#start"  ) == SAMESTRING) {
  318.         printf("#start procedure '%s'\n", var);
  319.         if      (strCmp(var, "HANGUP"    ) == SAMESTRING) {
  320.             cfg.pHangUp     = offset;
  321.         } else if (strCmp(var, "INITPORT"  ) == SAMESTRING) {
  322.             cfg.pInitPort   = offset;
  323.         } else if (strCmp(var, "CARRDETECT") == SAMESTRING) {
  324.             cfg.pCarrDetect = offset;
  325.         } else if (strCmp(var, "MIREADY"   ) == SAMESTRING) {
  326.             cfg.pMIReady    = offset;
  327.         } else if (strCmp(var, "MOREADY"   ) == SAMESTRING) {
  328.             cfg.pMOReady    = offset;
  329.         } else if (strCmp(var, "SET300"    ) == SAMESTRING) {
  330.             cfg.pBauds[ONLY_300] = offset;
  331.         } else if (strCmp(var, "SET1200"   ) == SAMESTRING) {
  332.             cfg.pBauds[BOTH_300_1200] = offset;
  333.         } else if (strCmp(var, "SET2400"   ) == SAMESTRING) {
  334.             cfg.pBauds[TH_3_12_24] = offset;
  335.         } else if (strCmp(var, "SET_HIGHER") == SAMESTRING) {
  336.             cfg.pBauds[SetYourOwn] = offset;
  337.         } else if (strCmp(var, "CHECKBAUD" ) == SAMESTRING) {
  338.             cfg.pCheckBaud  = offset;
  339. #ifndef MSDOS
  340.         } else if (strCmp(var, "INITDATE"  ) == SAMESTRING) {
  341.             cfg.pInitDate   = offset;
  342.         } else if (strCmp(var, "GETDAY"    ) == SAMESTRING) {
  343.             cfg.pGetDay     = offset;
  344.         } else if (strCmp(var, "GETMONTH"  ) == SAMESTRING) {
  345.             cfg.pGetMonth   = offset;
  346.         } else if (strCmp(var, "GETYEAR"   ) == SAMESTRING) {
  347.             cfg.pGetYear    = offset;
  348. #endif
  349.         } else printf("?--no procedure '%s' known!\n", var);
  350.  
  351.         } else if (strCmp(cmd, "#code"   ) == SAMESTRING) {
  352.         printf("#code '%s'\n", var);
  353.         if      (strCmp(var, "LOAD"       ) == SAMESTRING) {
  354.             *nextCode.pc++    = LOAD;
  355.             *nextCode.pi++    = arg;
  356.             offset += 3;
  357.         } else if (strCmp(var, "ANDI"       ) == SAMESTRING) {
  358.             *nextCode.pc++    = ANDI;
  359.             *nextCode.pc++    = arg;
  360.             offset += 2;
  361.         } else if (strCmp(var, "ORI"       ) == SAMESTRING) {
  362.             *nextCode.pc++    = ORI;
  363.             *nextCode.pc++    =arg;
  364.             offset += 2;
  365.         } else if (strCmp(var, "XORI"       ) == SAMESTRING) {
  366.             *nextCode.pc++    = XORI;
  367.             *nextCode.pc++    = arg;
  368.             offset += 2;
  369.         } else if (strCmp(var, "STORE"       ) == SAMESTRING) {
  370.             *nextCode.pc++    = STORE;
  371.             *nextCode.pi++    = arg;
  372.             offset += 3;
  373.         } else if (strCmp(var, "LOADI"       ) == SAMESTRING) {
  374.             *nextCode.pc++    = LOADI;
  375.             *nextCode.pc++    = arg;
  376.             offset += 2;
  377.         } else if (strCmp(var, "RET"       ) == SAMESTRING) {
  378.             *nextCode.pc++    = RET;
  379.             offset++;
  380.         } else if (strCmp(var, "INP"       ) == SAMESTRING) {
  381.             *nextCode.pc++    = INP;
  382.             *nextCode.pi++    = arg;
  383.             offset += 3;
  384.         } else if (strCmp(var, "OUTP"       ) == SAMESTRING) {
  385.             *nextCode.pc++    = OUTP;
  386.             *nextCode.pi++    = arg;
  387.             offset += 3;
  388.         } else if (strCmp(var, "PAUSEI"    ) == SAMESTRING) {
  389.             *nextCode.pc++    = PAUSEI;
  390.             *nextCode.pc++    = arg;
  391.             offset += 2;
  392.         } else if (strCmp(var, "ARRAY[]="  ) == SAMESTRING) {
  393.             *nextCode.pc++    = STOREX;
  394.             *nextCode.pc++    = arg;
  395.             offset += 2;
  396.         } else if (strCmp(var, "ARRAY[]"   ) == SAMESTRING) {
  397.             *nextCode.pc++    = LOADX;
  398.             *nextCode.pc++    = arg;
  399.             offset += 2;
  400.         } else if (strCmp(var, "OPR#"       ) == SAMESTRING) {
  401.             *nextCode.pc++    = OPRNUMBER;
  402.             offset++;
  403.  
  404.             /* reparse to pick up string: */
  405.             sscanf(line, "%s %s \"%s\" %d %d",
  406.             cmd, var, string, &arg, &arg2
  407.             );
  408.          /* BDS was excellent.  C86 sucks.    Reparse by hand <sigh>: */
  409.             for (i = strLen(line) - 1; line[i] != '"'; i--)
  410.             ;
  411.             sscanf(line + ++i, " %d %d", &arg, &arg2);
  412.  
  413.             string[strLen(string) - 1] = '\0';    /* Bug kludge    */
  414.             /* copy string into code buffer: */
  415.             strCpy(nextCode.pc, string);
  416.             while (*nextCode.pc++)    /* step over string    */
  417.             offset++;
  418.             offset++;
  419.             *nextCode.pc++    = arg;    /* lower limit        */
  420.             *nextCode.pc++    = arg2; /* upper limit        */
  421.             offset += 2;
  422.         } else if (strCmp(var, "OUTSTRING" ) == SAMESTRING) {
  423.             *nextCode.pc++    = OUTSTRING;
  424.             offset++;
  425.             /* reparse to pick up string: */
  426. /*            sscanf(line, "%s %s \"%s\"", cmd, var, string);    */
  427. /* Reparse on our own (stupid scanf() function, it worked in BDS!): */
  428.             readString(line, nextCode.pc, TRUE);
  429.             while (*nextCode.pc++)    /* step over string    */
  430.             offset++;
  431.             offset++;
  432.             nextCode.pc--;
  433.             *nextCode.pc++    = '\r'; /* add a CR        */
  434.             *nextCode.pc++    = '\0'; /* tie off with null    */
  435.             offset++;
  436.         } else printf("?--no code '%s'!\n", var);
  437.  
  438.         } else if (strCmp(cmd, "#nodeTitle") == SAMESTRING) {
  439.             readString(line, nextCode.pc, TRUE);
  440.             cfg.nodeTitle   = offset;
  441.             while (*nextCode.pc++)    /* step over string    */
  442.             offset++;
  443.             offset++;         /* I don't know why, but it works    */
  444.  
  445.         } else if (strCmp(cmd, "#sysPassword") == SAMESTRING) {
  446.             readString(line, cfg.sysPassword, FALSE);
  447.             if ((pwdfl = fopen(cfg.sysPassword, "r")) == NULL)
  448.             printf("\nNo system password file found\n");
  449.             else {
  450.             fgets(cfg.sysPassword, 199, pwdfl);
  451.             cfg.sysPassword[strLen(cfg.sysPassword) - 1] = 0;
  452.             if (strLen(cfg.sysPassword) < 15) {
  453.               printf("\nSystem password is too short -- ignored\n");
  454.                 cfg.sysPassword[0] = 0;
  455.             }
  456.             fclose(pwdfl);
  457.             }
  458.  
  459.         } else if (strCmp(cmd, "#callOutSuffix") == SAMESTRING) {
  460.             readString(line, nextCode.pc, TRUE);
  461.             cfg.netSuffix = offset;
  462.             while (*nextCode.pc++)    /* step over string    */
  463.             offset++;
  464.             offset++;         /* I don't know why, but it works    */
  465.         } else if (strCmp(cmd, "#callOutPrefix") == SAMESTRING) {
  466.             readString(line, nextCode.pc, TRUE);
  467.             cfg.netPrefix = offset;
  468.             while (*nextCode.pc++)    /* step over string    */
  469.             offset++;
  470.             offset++;         /* I don't know why, but it works    */
  471.  
  472.         } else if (strCmp(cmd, "#nodeName" ) == SAMESTRING) {
  473.             readString(line, nextCode.pc, FALSE);
  474.             if (strLen(nextCode.pc) > 19)
  475.             illegal("nodeName too long; must be less than 20");
  476.             cfg.nodeName    = offset;
  477.             while (*nextCode.pc++)    /* step over string    */
  478.             offset++;
  479.             offset++;         /* I don't know why, but it works    */
  480.         } else if (strCmp(cmd, "#nodeId"   ) == SAMESTRING) {
  481.             readString(line, nextCode.pc, FALSE);
  482.             if (strLen(nextCode.pc) > 19)
  483.             illegal("nodeId too long; must be less than 20");
  484.             cfg.nodeId        = offset;
  485.             while (*nextCode.pc++)    /* step over string    */
  486.             offset++;
  487.             offset++;         /* I don't know why, but it works    */
  488.             } else if (strCmp(cmd, "#baseRoom") == SAMESTRING) {
  489.             readString(line, nextCode.pc, TRUE);
  490.             if (strLen(nextCode.pc) > 19)
  491.             illegal("baseRoom too long; must be less than 20");
  492.             cfg.bRoom = offset;
  493.             baseRoom = nextCode.pc;
  494.             while (*nextCode.pc++)
  495.              offset++;
  496.             offset++;
  497.         } else if (strCmp(cmd, "#alldone") == SAMESTRING) {
  498.         break;
  499.         } else if (cmd[0] == '#') printf("? -- no '%s' command!\n", cmd);
  500.     }
  501.     }
  502.     if (nextCode.pc < &cfg.codeBuf[MAXCODE]) {
  503.        init(!(argc - 1));
  504.        wrapup();
  505.     } else {
  506.     illegal(
  507. "\7codeBuf[] overflow! Recompile with larger MAXCODE or reduce ctdlCnfg.sys\7"
  508.     );
  509.     }
  510. }
  511.  
  512. /***********************************************************************/
  513. /*    readString() reads a '#<id> "<value>"  since scanf can't         */
  514. /***********************************************************************/
  515. readString(source, destination, doProc)
  516. char *source, *destination;
  517. char doProc;
  518. {
  519.     char string[300], last = 0;
  520.     int  i, j;
  521.  
  522.     for (i = 0; source[i] != '"'; i++)
  523.         ;
  524.     for (j = 0, i++; source[i] != '"' || last == '\\'; i++, j++) {
  525.         string[j] = source[i];
  526.     last = source[i];
  527.     }
  528.     string[j] = '\0';
  529.     strCpy(destination, string);
  530.     if (doProc) xlatfmt(destination);
  531. }
  532.  
  533. /************************************************************************/
  534. /*    isoctal() xlatfmt() -- contributed by Dale Schumacher, allow    */
  535. /*    embedding of formatting info a la' "C" style: \n, \t, etc....    */
  536. /************************************************************************/
  537. isoctal( c )
  538. int c;
  539. {
  540.         return(( c >= '0' ) && ( c <= '7' ));
  541. }
  542.  
  543. xlatfmt( s )
  544. char *s;
  545. {
  546.         register char *p, *q;
  547.         register int i;
  548.  
  549.         for( p=q=s; *q; ++q ) {
  550.                 if ( *q == '\\' )
  551.                         switch( *++q ) {
  552.                                 case 'n' :
  553.                                         *p++ = '\n';
  554.                                         break;
  555.                                 case 't' :
  556.                                         *p++ = '\t';
  557.                                         break;
  558.                                 case 'b' :
  559.                                         *p++ = '\b';
  560.                                         break;
  561.                                 case 'r' :
  562.                                         *p++ = '\r';
  563.                                         break;
  564.                                 case 'f' :
  565.                                         *p++ = '\f';
  566.                                         break;
  567.                                 default :
  568.                                         if ( isoctal( *q )) {
  569.                                                 i = (( *q++ ) - '0' );
  570.                                                 if ( isoctal( *q )) {
  571.                                                         i <<= 3;
  572.                                                         i += (( *q++ ) - '0' );
  573.                                                         if ( isoctal( *q )) {
  574.                                                                 i <<= 3;
  575.                                                                 i += (*q -'0');
  576.                                                         }
  577.                                                         else
  578.                                                              --q;
  579.                                                 }
  580.                                                 else
  581.                                                         --q;
  582.                                                 *p++ = 0xFF & ((char) i);
  583.                                         }
  584.                                         else
  585.                                                 *p++ = *q;
  586.                                         break;
  587.                         }
  588.                 else
  589.                         *p++ = *q;
  590.         }
  591.         *p = '\0';
  592.         return( s );
  593. }
  594.  
  595. /***********************************************************************/
  596. /*    illegal() Prints out configur error message and aborts           */
  597. /***********************************************************************/
  598. illegal(errorstring)
  599. char *errorstring;
  600. {
  601.     printf("\007\nERROR IN CONFIGURATION:\n%s\nABORTING", errorstring);
  602.     exit(7);
  603. }
  604.  
  605. /************************************************************************/
  606. /*    dGetWord() fetches one word from current message, off disk    */
  607. /*    returns TRUE if more words follow, else FALSE            */
  608. /************************************************************************/
  609. char dGetWord(dest, lim)
  610. char *dest;
  611. int  lim;
  612. {
  613.     char c;
  614.  
  615.     --lim;    /* play it safe */
  616.  
  617.     /* pick up any leading blanks: */
  618.     for (c = getMsgChar();   c == ' '  &&  c && lim;   c = getMsgChar()) {
  619.     if (lim) { *dest++ = c;   lim--; }
  620.     }
  621.  
  622.     /* step through word: */
  623.     for (         ;  c != ' ' && c && lim;   c = getMsgChar()) {
  624.     if (lim) { *dest++ = c;   lim--; }
  625.     }
  626.  
  627.     /* trailing blanks: */
  628.     for (         ;   c == ' ' && c && lim;   c = getMsgChar()) {
  629.     if (lim) { *dest++ = c;   lim--; }
  630.     }
  631.  
  632.     if (c)  unGetMsgChar(c);    /* took one too many    */
  633.  
  634.     *dest = '\0';        /* tie off string    */
  635.  
  636.     return  c;
  637. }
  638.  
  639. /************************************************************************/
  640. /*    getMessage() reads a message off disk into RAM.         */
  641. /*    a previous call to setUp has specified the message.        */
  642. /************************************************************************/
  643. getMessage()
  644. {
  645.     unsigned char c;
  646.  
  647.     /* clear msgBuf out */
  648.     msgBuf.mbauth[ 0]    = '\0';
  649.     msgBuf.mbdate[ 0]    = '\0';
  650.     msgBuf.mborig[ 0]    = '\0';
  651.     msgBuf.mboname[0]    = '\0';
  652.     msgBuf.mbroom[ 0]    = '\0';
  653.     msgBuf.mbsrcId[0]    = '\0';
  654.     msgBuf.mbtext[ 0]    = '\0';
  655.     msgBuf.mbto[   0]    = '\0';
  656.     msgBuf.mbaddr[ 0]    = '\0';
  657.  
  658.     do c = getMsgChar(); while (c != 0xFF);    /* find start of msg    */
  659.  
  660.     msgBuf.mbheadChar    = oldChar;        /* record location    */
  661.     msgBuf.mbheadSector = oldSector;
  662.  
  663.     getMsgStr(msgBuf.mbId, NAMESIZE);
  664.  
  665.     do    {
  666.     c = getMsgChar();
  667.     switch (c) {
  668.     case 'A':    getMsgStr(msgBuf.mbauth,  NAMESIZE);    break;
  669.     case 'D':    getMsgStr(msgBuf.mbdate,  NAMESIZE);    break;
  670.     case 'M':    /* just exit -- we'll read off disk */    break;
  671.     case 'N':    getMsgStr(msgBuf.mboname, NAMESIZE);    break;
  672.     case 'O':    getMsgStr(msgBuf.mborig,  NAMESIZE);    break;
  673.     case 'R':    getMsgStr(msgBuf.mbroom,  NAMESIZE);    break;
  674.     case 'S':    getMsgStr(msgBuf.mbsrcId, NAMESIZE);    break;
  675.     case 'T':    getMsgStr(msgBuf.mbto,      NAMESIZE);    break;
  676.     case 'Q':    getMsgStr(msgBuf.mbaddr,  NAMESIZE);    break;
  677.     default:
  678.         getMsgStr(msgBuf.mbtext, MAXTEXT);    /* discard unknown field  */
  679.         msgBuf.mbtext[0]    = '\0';
  680.         break;
  681.     }
  682.     } while (c != 'M'  &&  isAlpha(c));
  683.     if (strCmpU(msgBuf.mbroom, "Mail") == SAMESTRING) mailCount++;
  684. }
  685.  
  686. /************************************************************************/
  687. /*    getMsgChar() returns sequential chars from message on disk    */
  688. /************************************************************************/
  689. unsigned char getMsgChar()
  690. {
  691.     char toReturn;
  692.  
  693.     if (GMCCache) {    /* someone did an unGetMsgChar() --return it    */
  694.     toReturn= GMCCache;
  695.     GMCCache= '\0';
  696.     return toReturn;
  697.     }
  698.  
  699.     oldChar    = thisChar;
  700.     oldSector    = thisSector;
  701.  
  702.     toReturn    = sectBuf[thisChar];
  703.  
  704. #ifdef XYZZY
  705.     if (debug) putCh(visible(toReturn));
  706. #endif
  707.  
  708.     thisChar    = ++thisChar % SECTSIZE;
  709.     if (thisChar == 0) {
  710.     /* time to read next sector in: */
  711.     thisSector  = ++thisSector % cfg.maxMSector;
  712.     fseek(msgfl, (long) thisSector * SECTSIZE, 0);
  713.     if (fread(sectBuf, SECTSIZE, 1, msgfl) != 1) {
  714.         exit(printf("?nextMsgChar-read fail"));
  715.     }
  716.     crypte(sectBuf, SECTSIZE, 0);
  717.     }
  718.     return(toReturn);
  719. }
  720.  
  721. /************************************************************************/
  722. /*    getMsgStr() reads a string from message.buf            */
  723. /************************************************************************/
  724. getMsgStr(dest, lim)
  725. char *dest;
  726. int  lim;
  727. {
  728.     char c;
  729.  
  730.     while (c = getMsgChar()) {        /* read the complete string    */
  731.     if (lim) {            /* if we have room then     */
  732.         lim--;
  733.         *dest++ = c;        /* copy char to buffer        */
  734.     }
  735.     }
  736.     *dest = '\0';            /* tie string off with null    */
  737. }
  738.  
  739. /************************************************************************/
  740. /*    msgInit() sets up lowId, highId, cfg.catSector and cfg.catChar, */
  741. /*    by scanning over message.buf                    */
  742. /************************************************************************/
  743. msgInit()
  744. {
  745.     int   atoi();
  746.     ulong first, here;
  747.  
  748.     startAt(0, 0);
  749.     getMessage();
  750.  
  751.     /* get the ID# */
  752.     sscanf(msgBuf.mbId, "%ld", &first);
  753.     printf("message# %lu\n", first);
  754.  
  755.     cfg.newest = cfg.oldest = first;
  756.  
  757.     cfg.catSector   = thisSector;
  758.     cfg.catChar     = thisChar;
  759.  
  760.     for (getMessage();
  761.          sscanf(msgBuf.mbId, "%ld", &here), here != first;
  762.               getMessage()) {
  763.     printf("message# %lu\n", here);
  764.  
  765.     /* find highest and lowest message IDs: */
  766.     if (here < cfg.oldest) {
  767.         cfg.oldest = here;
  768.         printf(" oldest=%lu\n", cfg.oldest);
  769.     }
  770.     if (here > cfg.newest) {
  771.         cfg.newest = here;
  772.         printf(" newest=%lu\n", cfg.newest);
  773.  
  774.         /* read rest of message in and remember where it ends,    */
  775.         /* in case it turns out to be the last message        */
  776.         /* in which case, that's where to start writing next message*/
  777.         while (dGetWord(msgBuf.mbtext, MAXTEXT));
  778.         cfg.catSector   = thisSector;
  779.         cfg.catChar     = thisChar;
  780.     }
  781.     }
  782. }
  783.  
  784. /************************************************************************/
  785. /*    startAt() sets location to begin reading message from        */
  786. /************************************************************************/
  787. startAt(sect, byt)
  788. unsigned sect;
  789. int   byt;
  790. {
  791.     GMCCache  = '\0';    /* cache to unGetMsgChar() into */
  792.  
  793.     if (sect >= cfg.maxMSector) {
  794.     printf("?startAt s=%d,b=%d", sect, byt);
  795.     printf("?startAt crash");
  796.     exit();
  797.     }
  798.     thisChar    = byt;
  799.     thisSector    = sect;
  800.  
  801.     fseek(msgfl, SECTSIZE * sect, 0);
  802.     if (fread(sectBuf, SECTSIZE, 1, msgfl) != 1) {
  803.     printf("?startAt read fail");
  804.     }
  805.     crypte(sectBuf, SECTSIZE, 0);
  806. }
  807.  
  808. /************************************************************************/
  809. /*    unGetMsgChar() returns (at most one) char to getMsgChar()    */
  810. /************************************************************************/
  811. unGetMsgChar(c)
  812. unsigned char c;
  813. {
  814.     GMCCache    = c;
  815. }
  816.  
  817. /************************************************************************/
  818. /*    zapMsgFl() initializes message.buf                */
  819. /************************************************************************/
  820. zapMsgFile()
  821. {
  822.     label fn;
  823.  
  824.     printf("\nDestroy all current messages? ");
  825.     if (toUpper(getch()) != 'Y')   return FALSE;
  826.  
  827.     if (cfg.mirror) printf("Creating primary message file.\n");
  828.     realZap();
  829.     if (cfg.mirror) {
  830.     fclose(msgfl);
  831.     strCpy(fn, "a:ctdlmsg.sys");
  832.     fn[0] += cfg.mbkpDisk;
  833.     if ((msgfl = fopen(fn, "wrb")) == NULL)
  834.         illegal("?Can't create the secondary message file!");
  835.     printf("Creating secondary message file.\n");
  836.     realZap();
  837.     }
  838.     return TRUE;
  839. }
  840.  
  841. /************************************************************************/
  842. /*    realZap() does work of zapMsgFile                */
  843. /************************************************************************/
  844. realZap()
  845. {
  846.     int   i;
  847.     unsigned sect;
  848.  
  849.     /* put null message in first sector... */
  850.     sectBuf[0]    = 0xFF; /*   \                      */
  851.     sectBuf[1]    =  '1'; /*    >  Message ID "1" MS-DOS style  */
  852.     sectBuf[2]    = '\0'; /*   /                      */
  853.     sectBuf[3]    =  'M'; /*   \      Null messsage           */
  854.     sectBuf[4]    = '\0'; /*   /                      */
  855.  
  856.     cfg.newest = cfg.oldest = 1l;
  857.  
  858.     cfg.catSector   = 0;
  859.     cfg.catChar     = 5;
  860.  
  861.     for (i=5;  i<SECTSIZE;  i++) sectBuf[i] = 0;
  862.  
  863.     crypte(sectBuf, SECTSIZE, 0);    /* encrypt    */
  864.     if (fwrite(sectBuf, SECTSIZE, 1, msgfl) != 1) {
  865.     printf("zapMsgFil: write failed\n");
  866.     }
  867.  
  868.     crypte(sectBuf, SECTSIZE, 0);    /* decrypt    */
  869.     sectBuf[0] = 0;
  870.     crypte(sectBuf, SECTSIZE, 0);    /* encrypt    */
  871.     printf("\n%d sectors to be cleared\n", cfg.maxMSector);
  872.     for (sect = 1l;  sect < cfg.maxMSector;  sect++) {
  873.     printf("%u\r", sect);
  874.     if (fwrite(sectBuf, SECTSIZE, 1, msgfl) != 1) {
  875.         printf("zapMsgFil: write failed\n");
  876.     }
  877.     }
  878.     crypte(sectBuf, SECTSIZE, 0);    /* decrypt    */
  879.     return TRUE;
  880. }
  881.  
  882. /************************************************************************/
  883. /*    indexRooms() -- build RAM index to CTDLROOM.SYS, displays stats.*/
  884. /************************************************************************/
  885. indexRooms()
  886. {
  887.     int  goodRoom, m, roomCount, slot;
  888.  
  889.     roomCount = 0;
  890.     for (slot = 0;  slot < MAXROOMS;  slot++) {
  891.     getRoom(slot);
  892.     printf("Checking room #%d: ", slot);
  893.     if (roomBuf.rbflags.INUSE == 1) {
  894.         roomBuf.rbflags.INUSE = 0;        /* clear "inUse" flag */
  895.         for (m = 0, goodRoom = FALSE; m < MSGSPERRM && !goodRoom; m++) {
  896.         if (roomBuf.msg[m].rbmsgNo > cfg.oldest) {
  897.             goodRoom    = TRUE;
  898.         }
  899.         }
  900.         if (goodRoom   || roomBuf.rbflags.PERMROOM == 1)   {
  901.         roomBuf.rbflags.INUSE = 1;
  902.         }
  903.  
  904.         if (roomBuf.rbflags.INUSE == 1) {
  905.         if (slot == 0)               /* Ugly kludge */
  906.             strCpy(roomBuf.rbname, baseRoom);
  907.         roomCount++;
  908.         }
  909.         else {
  910.         zero_struct(roomBuf.rbflags);
  911.     /*    roomBuf.rbflags.INUSE     = 0;
  912.         roomBuf.rbflags.MSDOSDIR = 0;
  913.         roomBuf.rbflags.PERMROOM = 0;
  914.         roomBuf.rbflags.INUSE     = 0;    */
  915.         }
  916.     }
  917.     printf("%s\n",
  918.            (roomBuf.rbflags.INUSE == 1) ? roomBuf.rbname : "<not in use>");
  919.     noteRoom();
  920.     putRoom(slot);
  921.     }
  922.     printf(" %d of %d rooms in use\n", roomCount, MAXROOMS);
  923. }
  924.  
  925. /************************************************************************/
  926. /*    noteRoom() -- enter room into RAM index array.            */
  927. /************************************************************************/
  928. noteRoom()
  929. {
  930.     int   i;
  931.     ulong last;
  932.  
  933.     last = 0l;
  934.     for (i = 0;  i < MSGSPERROOM;  i++)  {
  935.     if (roomBuf.msg[i].rbmsgNo > cfg.newest) {
  936.         roomBuf.msg[i].rbmsgNo = 0l;
  937.     }
  938.     if (roomBuf.msg[i].rbmsgNo > last) {
  939.         last = roomBuf.msg[i].rbmsgNo;
  940.     }
  941.     }
  942.     roomTab[thisRoom].rtlastMessage = last         ;
  943.     strCpy(roomTab[thisRoom].rtname, roomBuf.rbname) ;
  944.     roomTab[thisRoom].rtgen           = roomBuf.rbgen    ;
  945.     copy_struct(roomBuf.rbflags, roomTab[thisRoom].rtflags);
  946. /*  roomTab[thisRoom].rtflags.INUSE    = roomBuf.rbflags.INUSE;
  947.     roomTab[thisRoom].rtflags.PUBLIC   = roomBuf.rbflags.PUBLIC;
  948.     roomTab[thisRoom].rtflags.MSDOSDIR = roomBuf.rbflags.MSDOSDIR;
  949.     roomTab[thisRoom].rtflags.PERMROOM = roomBuf.rbflags.PERMROOM;
  950.     roomTab[thisRoom].rtflags.SKIP     = roomBuf.rbflags.SKIP;
  951.     roomTab[thisRoom].rtflags.UPLOAD   = roomBuf.rbflags.UPLOAD;
  952.     roomTab[thisRoom].rtflags.DOWNLOAD = roomBuf.rbflags.DOWNLOAD;
  953.     roomTab[thisRoom].rtflags.SHARED   = roomBuf.rbflags.SHARED;    */
  954. }
  955.  
  956. /************************************************************************/
  957. /*    zapRoomFile() erases and re-initailizes CTDLROOM.SYS        */
  958. /************************************************************************/
  959. zapRoomFile()
  960. {
  961.     int i;
  962.  
  963.     printf("\nWipe room file? ");
  964.     if (toUpper(getch()) != 'Y') return FALSE;
  965.     printf("\n");
  966.  
  967.     zero_struct(roomBuf.rbflags);
  968.  
  969. /*  roomBuf.rbflags.INUSE    = FALSE;
  970.     roomBuf.rbflags.PUBLIC   = FALSE;
  971.     roomBuf.rbflags.MSDOSDIR = FALSE;
  972.     roomBuf.rbflags.PERMROOM = FALSE;
  973.     roomBuf.rbflags.SKIP     = FALSE;    */
  974.     roomBuf.rbgen         = 0;
  975.     roomBuf.rbdisk         = 0;
  976.     roomBuf.rbdirname[0]     = 0;
  977.     roomBuf.rbname[0]         = 0;   /* unnecessary -- but I like it...    */
  978.     for (i = 0;  i < MSGSPERRM;  i++) {
  979.     roomBuf.msg[i].rbmsgNo =  0l;
  980.     roomBuf.msg[i].rbmsgLoc = 0 ;
  981.     }
  982.  
  983.     printf("maxrooms=%d\n", MAXROOMS);
  984.  
  985.     for (i = 0;  i < MAXROOMS;    i++) {
  986.     printf("clearing room %d\n", i);
  987.     putRoom(i);
  988.     noteRoom();
  989.     }
  990.  
  991.     /* Lobby> always exists -- guarantees us a place to stand! */
  992.     thisRoom        = 0        ;
  993.     strCpy(roomBuf.rbname, baseRoom)    ;
  994.     roomBuf.rbflags.PERMROOM = TRUE;
  995.     roomBuf.rbflags.PUBLIC   = TRUE;
  996.     roomBuf.rbflags.INUSE    = TRUE;
  997.  
  998.     putRoom(LOBBY);
  999.     noteRoom();
  1000.  
  1001.     /* Mail> is also permanent...    */
  1002.     thisRoom        = MAILROOM    ;
  1003.     strCpy(roomBuf.rbname, "Mail")    ;
  1004.     /* Don't bother to copy flags, they remain the same (right?)    */
  1005.     putRoom(MAILROOM);
  1006.     noteRoom();
  1007.  
  1008.     /* Aide> also...            */
  1009.     thisRoom        = AIDEROOM    ;
  1010.     strCpy(roomBuf.rbname, "Aide")    ;
  1011.     roomBuf.rbflags.PERMROOM = TRUE;
  1012.     roomBuf.rbflags.PUBLIC   = FALSE;
  1013.     roomBuf.rbflags.INUSE    = TRUE;
  1014.     putRoom(AIDEROOM);
  1015.     noteRoom();
  1016.  
  1017.     return TRUE;
  1018. }
  1019.  
  1020. /************************************************************************/
  1021. /*    setSpace() moves us to a disk and user#             */
  1022. /************************************************************************/
  1023. #define SETDISK     14
  1024. setSpace(disk, dir)
  1025. char disk;
  1026. char *dir;
  1027. {
  1028.     bdos(SETDISK, disk);
  1029.     cfg.ourDisk     = disk;
  1030.  
  1031.     if (strCmp(dir, "") == SAMESTRING) {
  1032.     strCpy(cfg.ourUser, "..");
  1033.     }
  1034.     else {
  1035.     strCpy(cfg.ourUser, dir);
  1036.     if (chdir(dir) == EOF) {
  1037.         printf("?Directory not present!\n ");
  1038.         setSpace(cfg.homeDisk, "");
  1039.         return FALSE;
  1040.     }
  1041.     }
  1042.     return TRUE;
  1043. }
  1044.  
  1045. /************************************************************************/
  1046. /*    hash() hashes a string to an integer                */
  1047. /************************************************************************/
  1048. int hash(str)
  1049. char *str;
  1050. {
  1051.     int  h, i, shift;
  1052.  
  1053.     for (h=shift=0;  *str;  shift=(shift+1)&7, str++) {
  1054.     h ^= (i=toUpper(*str)) << shift;
  1055.     }
  1056.     return h;
  1057. }
  1058.  
  1059. /************************************************************************/
  1060. /*    logInit() indexes ctdllog.sys                    */
  1061. /************************************************************************/
  1062. logInit()
  1063. {
  1064.     int i;
  1065.     int logSort();
  1066.     int count = 0;
  1067.     long rewind();
  1068.  
  1069.     if (rewind(logfl) != 0l) illegal("Rewinding logfl failed!");
  1070.     /* clear logTab */
  1071.     for (i = 0; i < cfg.MAXLOGTAB; i++) logTab[i].ltnewest = 0l;
  1072.  
  1073.     /* load logTab: */
  1074.     for (thisLog = 0;  thisLog < cfg.MAXLOGTAB;  thisLog++) {
  1075.     printf("log#%3d", thisLog);
  1076.     getLog(&logBuf, thisLog);
  1077.  
  1078.     /* count valid entries:         */
  1079.     if (logBuf.lbflags.L_INUSE == 1) {
  1080.         count++;
  1081.         printf("   %s", logBuf.lbname);
  1082.     }
  1083.     else printf("    <not in use>");
  1084.     printf("\n");
  1085.  
  1086.     /* copy relevant info into index:   */
  1087.     logTab[thisLog].ltnewest = logBuf.lbvisit[0];
  1088.     logTab[thisLog].ltlogSlot= thisLog;
  1089.     if (logBuf.lbflags.L_INUSE == 1) {
  1090.         logTab[thisLog].ltnmhash = hash(logBuf.lbname);
  1091.         logTab[thisLog].ltpwhash = hash(logBuf.lbpw  );
  1092.     }
  1093.     else {
  1094.         logTab[thisLog].ltnmhash = 0;
  1095.         logTab[thisLog].ltpwhash = 0;
  1096.     }
  1097.     }
  1098.     printf(" logInit--%d valid log entries\n", count);
  1099.     printf("sortLog...\n");
  1100.     qsort(logTab, cfg.MAXLOGTAB, cfg.sizeLTentry, logSort);
  1101. }
  1102.  
  1103. /************************************************************************/
  1104. /*    logSort() Sorts 2 entries in logTab                */
  1105. /************************************************************************/
  1106. int logSort(s1, s2)
  1107. struct lTable *s1, *s2;
  1108. {
  1109.     if (s1->ltnmhash == 0 && s2->ltnmhash == 0)
  1110.     return 0;
  1111.     if (s1->ltnmhash == 0 && s2->ltnmhash != 0)
  1112.     return 1;
  1113.     if (s1->ltnmhash != 0 && s2->ltnmhash == 0)
  1114.     return -1;
  1115.     if (s1->ltnewest < s2->ltnewest)
  1116.     return 1;
  1117.     if (s1->ltnewest > s2->ltnewest)
  1118.     return -1;
  1119.     return 0;
  1120. }
  1121.  
  1122. /************************************************************************/
  1123. /*    noteLog() notes logTab entry in RAM buffer in master index    */
  1124. /************************************************************************/
  1125. noteLog()
  1126. {
  1127.     int i, slot;
  1128.  
  1129.     /* figure out who it belongs between:    */
  1130.     for (i = 0;  logTab[i].ltnewest > logBuf.lbvisit[0];  i++);
  1131.  
  1132.     /* note location and open it up:        */
  1133.     slot = i;
  1134.     slideLTab(slot, cfg.MAXLOGTAB-1);
  1135.  
  1136.     /* insert new record */
  1137.     logTab[slot].ltnewest    = logBuf.lbvisit[0]  ;
  1138.     logTab[slot].ltlogSlot    = thisLog         ;
  1139.     logTab[slot].ltpwhash    = hash(logBuf.lbpw)  ;
  1140.     logTab[slot].ltnmhash    = hash(logBuf.lbname);
  1141. }
  1142.  
  1143. /************************************************************************/
  1144. /*    slideLTab() slides bottom N lots in logTab down.  For sorting.    */
  1145. /************************************************************************/
  1146. slideLTab(slot, last)
  1147. int slot;
  1148. int last;
  1149. {
  1150.     int i;
  1151.  
  1152.     /* open slot up: (movmem isn't guaranteed on overlaps) */
  1153.     for (i = last - 1;    i >= slot;  i--)  {
  1154.     movmem(&logTab[i], &logTab[i + 1], cfg.sizeLTentry);
  1155.     }
  1156. }
  1157.  
  1158. /************************************************************************/
  1159. /*    wrapup() finishes up and writes ctdlTabl.sys out, finally    */
  1160. /************************************************************************/
  1161. wrapup()
  1162. {
  1163.     printf("\ncreating ctdlTabl.sys table\n");
  1164.     if (!msgZap)  msgInit();
  1165.     if (!roomZap) indexRooms();
  1166.     cfg.weAre = CITADEL;
  1167.     if (!logZap)  logInit();
  1168.     netInit();
  1169.     fclose(netfl);
  1170.     fclose(roomfl);
  1171.     fclose(msgfl);
  1172.     fclose(logfl);
  1173.     printf("%ld of the messages were Mail\n", mailCount);
  1174.     printf("writeSysTab = %d\n", writeSysTab());
  1175. }
  1176.  
  1177. /************************************************************************/
  1178. /*    zapLogFile() erases & re-initializes userlog.buf        */
  1179. /************************************************************************/
  1180. zapLogFile()
  1181. {
  1182.     int  i;
  1183.  
  1184.     printf("\nWipe out log file? ");
  1185.     if (toUpper(getch()) != 'Y')   return FALSE;
  1186.     printf("\n");
  1187.  
  1188.     /* clear RAM buffer out:            */
  1189.     logBuf.lbflags.L_INUSE = FALSE;
  1190.     for (i = 0;  i < MAILSLOTS;  i++) {
  1191.     logBuf.lbslot[i] = 0l;
  1192.     logBuf.lbId[i]     = 0l;
  1193.     }
  1194.     for (i = 0;  i < NAMESIZE;    i++) {
  1195.     logBuf.lbname[i] = 0;
  1196.     logBuf.lbpw[i]     = 0;
  1197.     }
  1198.  
  1199.     /* write empty buffer all over file;    */
  1200.     for (i = 0; i < cfg.MAXLOGTAB;  i++) {
  1201.     printf("Clearing log #%d\n", i);
  1202.     putLog(&logBuf, i);
  1203.     logTab[i].ltnewest = logBuf.lbvisit[0];
  1204.     logTab[i].ltlogSlot= i;
  1205.     logTab[i].ltnmhash = hash(logBuf.lbname);
  1206.     logTab[i].ltpwhash = hash(logBuf.lbpw  );
  1207.     }
  1208.     return TRUE;
  1209. }
  1210.  
  1211. getch()
  1212. {
  1213.     return bdos(7);
  1214. }
  1215.  
  1216. /************************************************************************/
  1217. /*    netInit() Initialize RAM index for net                */
  1218. /************************************************************************/
  1219. netInit()
  1220. {
  1221.     label temp;
  1222.     int i = 0;
  1223.  
  1224.     cfg.netSize = (int) ((fseek(netfl, -1l, 2) + 1) / sizeof (netBuf));
  1225.     netTab    = (struct netTable *) malloc(sizeof (*netTab) * cfg.netSize);
  1226.     while (i < cfg.netSize) {
  1227.     getNet(i);
  1228.     normId(netBuf.netId, temp);
  1229.     netTab[i].ntnmhash = hash(netBuf.netName);
  1230.     netTab[i].ntidhash = hash(temp);
  1231.     netTab[i].ntflags.in_use = netBuf.nbflags.in_use;
  1232.     netTab[i].ntflags.normal_mail = netBuf.nbflags.normal_mail;
  1233.     netTab[i].ntflags.room_files  = netBuf.nbflags.room_files;
  1234.     printf("System %3d. %s\n", i,
  1235.        (netBuf.nbflags.in_use) ? netBuf.netName : "<not in use>");
  1236.     i++;
  1237.     }
  1238. }
  1239.  
  1240. /************************************************************************/
  1241. /*    strCmpU() is strcmp(), but ignoring case distinctions        */
  1242. /************************************************************************/
  1243. int strCmpU(s, t)
  1244. char s[], t[];
  1245. {
  1246.     int  i;
  1247.  
  1248.     i = 0;
  1249.  
  1250.     while (toUpper(s[i]) == toUpper(t[i])) {
  1251.     if (s[i++] == '\0')  return 0;
  1252.     }
  1253.     return  toUpper(s[i]) - toUpper(t[i]);
  1254. }
  1255.  
  1256. /************************************************************************/
  1257. /*    normId() Normalizes a node id.                    */
  1258. /************************************************************************/
  1259. normId(source, dest)
  1260. label source, dest;
  1261. {
  1262.     while (!isalpha(*source) && *source)
  1263.     source++;
  1264.     if (!*source) return FALSE;
  1265.     *dest++ = toUpper(*source++);
  1266.     while (!isalpha(*source) && *source)
  1267.     source++;
  1268.     if (!*source) return FALSE;
  1269.     *dest++ = toUpper(*source++);
  1270.     while (*source) {
  1271.     if (isdigit(*source))
  1272.         *dest++ = *source;
  1273.     source++;
  1274.     }
  1275.     *dest = '\0';
  1276.     return TRUE;
  1277. }
  1278.  
  1279. /************************************************************************/
  1280. /*    crashout() fatal error, for library functions            */
  1281. /************************************************************************/
  1282. crashout(str)
  1283. char *str;
  1284. {
  1285.     illegal(str);
  1286. }
  1287.